<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Shoutbox</title>
    
    <style type="text/css">
        body, h1 { margin:0;padding:0; }
        .space-line {clear:both;}
        .box    {color:black;
                width:inherit;
                height:85%;
                overflow:scroll;
                font-size:inherit;
                background-color:#E9E9E9;
                font-family: "Monotype";
                margin:0; padding:0;}

        .header{font-family:inherit; font-size:inherit;background-color:lightgrey;width:inherit;}
        .boxh    {background-color:lightgrey;
                width:inherit;
                font-size:10pt;
                font-family:monospace;
                height:100%;
                float:left;}
        .margin{width:10px;float:left;
                height:inherit;
                }
        #inputbox{width:580px;float:left;}
        #inputbox2{width:130px;float:left;}
    </style>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script type="text/javascript" src="http://comet.${servicesurl}/_/comet.js"></script> 
</head>
  <body>
  <script>
    /* yep. we have to change document.domain */
    document.domain = extract_xss_domain(document.domain);
    
    var channel_id = '';
    var gc;
    function get_comet_uri(){
        return('/comet/'+ channel_id + '/listen?z='+Math.random() +'&last_eventid=' + max_id + '&username=' + '${username}' );
    }
    
    update_scheduled = false;
    function update_uri() {
        var xhr;
        function ajax_callback(){
            if(xhr.readyState != 4)
                return;
            if(xhr.status != 200){
                //alert('failed to get channel_id. is google working?');
                setTimeout('update_uri()', 1000*30);
                update_scheduled = false;
                return;
            }
            var r = false;
            if(xhr.responseText){
                var j = eval('(' + xhr.responseText + ')');// json here
                if(channel_id != j.channel_id){
                    r = true;
                    /* set event history */
                    var ta = document.getElementById('slot');
                    ta.innerHTML = ta.innerHTML + '-- new channel_id:' + j.channel_id + '<br />' + replaceExtChars(j.events.join('\n')).split('\n').join('<br />') + '<br />--<br />';
                    ta.scrollTop = ta.scrollHeight;
                    channel_id = j.channel_id;
                    max_id     = j.max_id;
                }
                /* update userlist */
                userlist_clear();
                for(var i=0;i<j.userlist.length; i++){
                    userlist_append(j.userlist[i]);
                }
            }
            if(r){
                if(gc)
                    gc();
                gc = comet_schedule_crossdomain('http://comet.${domain}/_/iframe.html?a=a', get_comet_uri, comet_callback);
            }
            update_scheduled = false;
        };
        if(update_scheduled)
            return;
        if(xhr)
            xhr.abort();
        xhr = create_xhr();
        xhr.onreadystatechange = ajax_callback;
        xhr.open('GET', '/shoutbox/channel_uri?a=' + Math.random(), true);
        xhr.send(null);
        update_scheduled = true;
    }
    update_uri();
    
    userlist = [];
    function userlist_clear(){
        userlist = [];
        userlist_view();
    }
    function userlist_append(username){
        userlist = userlist.concat([username]).sort();
        userlist_view();
    }
    function userlist_remove(username){
        for(i=0; i<userlist.length; i++){
            if(userlist[i] == username){
                userlist = userlist.slice(0,i).concat( userlist.slice(i+1) );
                break;
            }
        }
        userlist_view();
    }
    function userlist_view(){
        var ta = document.getElementById('userlist');
        ta.innerHTML = userlist.join('<br />\n');
    }
    var max_id = 0;
    
    function comet_callback(data){
        var a = data.split(' ');
        var id    = a[0];
        var owner = a[1];
        
        
        /* system messages */
        if(id == 'connected'){
            return;
        }
        if(id == 'ping'){
            return;
        }
        if(id == 'destroyed'){
            channel_id = '';
            /* you can't just do update_uri() due to bug in safari */
            setTimeout("update_uri();", 500);
            return;
        }
        id = Number(id);
        if(id <= max_id){// ignore old events
            return;
        }
        max_id = id;
        
        /* login/logout */
        var command   = a[2];
        var parameter = a[3];
        if(command == 'login' && owner == 'admin'){
            userlist_append(parameter);
            return;
        }
        if(command == 'logout' && owner == 'admin'){
            userlist_remove(parameter);
            return;
        }
        
        /* user event */
        var data  = a.slice(2).join(' ');
        var ta = document.getElementById('slot');
        ta.innerHTML = ta.innerHTML + replaceExtChars(data) + '<br />';
        ta.scrollTop = ta.scrollHeight;
    }
    var fromTo = new Array( '&amp;','&', 
                            '&lt;', '<', 
                            '&gt;', '>', 
                            '&quot;', "\"");
    function replaceExtChars(text) {
        for (i=0; i < fromTo.length; i=i+2)
            text = text.replace(eval('/'+fromTo[i+1]+'/g'), fromTo[i]);
        text = text.replace(/\n/g, '<br class="space-line" />');
        text = text.replace(/\r/g, '');
        return (text);
    }
    
        
    function submiter(formObject){
        try{
            var textbox = document.getElementById('inputbox');
            if(textbox.value=='')
                return false;
                
            var v = escape('${username}: ' + textbox.value).replace(/\+/g, '%2B');
            
            /* not safe at all - but we don't have any kind of auth */
            var formObject = document.getElementById('theForm');
            function cb(xhr){
                if(xhr.readyState != 4)
                    return;
                if(xhr.status != 200){
                    channel_id = '';
                    update_uri();
                }
            }
            ajax_crossdomain('http://comet.${domain}/_/crossajax.html?a=a', 'POST', '/comet/' + channel_id + '/event', cb,
                    'data=' + v );
            
            textbox.value='';
            textbox.focus();
            return false;
        }catch(e){
            alert('error sending' + e);
        }
        return false;
    }
    </script>
    
    <div style="height:400px">
        <div class="boxh" style="width:650px">
            <div class="header">---------- #shoutbox ${username} --------</div><div class="space-line"></div>
            <div id="slot" class="box"></div>
            <div>
                Type message:
                <div style="float:left;">
                    <form action="." method="post" onsubmit="return submiter()" id="theForm" autocomplete="off">
                        <input type="text" name="data" value="" id="inputbox" />
                        <input type="hidden" name="username" value="${username}" />
                        <input type="submit" value="ok" />
                    </form>
                </div>
            </div>
        </div>
        <div class="margin">
            &nbsp;
        </div>
        <div class="boxh" style="width:200px">
            <div class="header">-- users --</div>
            <div id="userlist" class="box"></div>
            <div>
                Set your username:
                <div style="float:left;">
                    <form action="." method="get" >
                        <input type="text" name="username" value="${username}" id="inputbox2"/>
                        <input type="submit" value="ok" />
                    </form>
                </div>
            </div>
        </div>
    </div>

    <script>
            document.getElementById('inputbox').focus();
    </script>

    <br />
    <br />
    <br />
    <div>
        You should know that:
        <ul>
            <li>this website is hosted on <a href="http://code.google.com/appengine/">Google App Engine</a></li>
            <li>it's using external <a href="http://movq.net">comet service</a></li>
            <li>the sources are <a href="http://code.google.com/p/gae-services-examples/source/browse">availbe public</a></li>
            <li>the users of this chat are not authorized! one user can easilly send message as another one.</li>
            
        </ul>
    </div>

</body>
</html>
